#include "include.h"

#if FUNC_FMRX_EN
AT(.com_text.fmrx.isr)
void fmrx_tmr1ms_isr(void)
{
    if (func_cb.sta == FUNC_FMRX) {
        fmrx_dac_sync();
    }
}

AT(.text.bsp.fmrx)
bool fmrx_is_playing(void)
{
    if (fmrx_cb.sta == FMRX_PLAY) {
        return true;
    }
    return false;
}

AT(.text.bsp.fmrx)
u8 get_fmrx_seek_staus(void)
{
    return fmrx_cb.seek_start;
}

AT(.text.bsp.fmrx)
void set_fmrx_seek_staus(u8 val)
{
    fmrx_cb.seek_start = val;
}

AT(.text.fmrx)
u8 fmrx_sysclk_config(void)
{
    return SYS_26M;
}

//库中默认同名WEAK函数返回true:内部会根据电台质量,差台会自动切到窄filter中,减少噪音成分. 但会导致指标测试时75K调制信号有些失真.
//若客户反馈指标测试时75K调制信号有些失真时,可以打开下面该函数返回false. 则FM会一直使用宽filter. 可以修正75K调制信号失真问题。
//AT(.text.fmrx)
//u8 fmrx_auto_narrow_filter(void)
//{
//    return false;
//}

//AT(.text.fmrx)
//u8 fmrx_dc_more_ch(void)   //打开这个函数，返回位为1越多，判台时放进来的台越多
//{
//    return BIT(0);
//}

/*
//常见修改总结,
1. 找一台客户能接受的FM样机，手动对比每个台的清晰度(可打开宏 FMRX_TEST_TBL_FREQ)
   如果多个台清晰度都不足,则需要考虑更改硬件PCB或尝试配置软件上RF相关参数，试试有无改善。
   1). 软件上对电台清晰度可能有影响的配置函数如下(可打开宏FMRX_OPTIMIZE_TRY，去配置以下函数的不同参数)：
	fmrx_set_rf_cap(31);     // 0~31 RF电容配置
	fmrx_set_rf_res(3);      // 0~3  RF电阻配置
 	fmrx_set_rf_fbres(0);    // 0~3  FB_RF电阻配置
    fmop_clk_gat_set();      // clk分频,时钟控制等
    如果软件更改上面的4个API提供的参数还是无效，则要优先考虑更改优化PCB了

2. 如果对比每个台的清晰度都差不多，则可以更改如下的判台参数控制搜台数量
  常见判台参数调节 (各参数建议以10%~20%的调节后去测试)：
  1) 搜台数不足:
      fmrx_thd.r_val = 50;    //减少rssi阀值. 多放点台进来
      fmrx_thd.z_val = 1400;  //值越大, 放进来的台越多.
      fmrx_thd.fz_val = 800;  //值越大, 放进来的台越多.
      fmrx_thd.d_val = 3000.  //此值保留, 影响不大, 3000左右即可. 台不足可以放大此值.

  2) 搜台数过多,杂台过多:
      fmrx_thd.r_val = 60;      //增加 rssi阀值. 少放点台进来.
      fmrx_thd.z_val = 1100;  //值越小, 放进来的台越少.
      fmrx_thd.fz_val = 600;   //值越小, 放进来的台越少.
      fmrx_thd.d_val = 3000.  //此值保留, 影响不大,3000左右即可.  杂台过多可以减少此值
*/

AT(.text.bsp.fmrx)
void fmrx_threshold_init(void)
{
    fmrx_thd.r_val = FMRX_THRESHOLD_VAL;
    fmrx_thd.z_val = FMRX_THRESHOLD_Z;
    fmrx_thd.fz_val = FMRX_THRESHOLD_FZ;
    fmrx_thd.d_val = FMRX_THRESHOLD_D;
}

#if FMRX_REC_EN
AT(.text.fmrx)
bool fmrx_auto_adjust_aupll_en(void)
{
    if (REC_STOP == rec_cb.sta) {
        return true;
    } else {
        return false;
    }

}
#endif // FMRX_REC_EN

AT(.text.bsp.fmrx)
void bsp_fmrx_init(void)
{
    printf("%s\n", __func__);

    fmrx_power_on(FMRX_THRESHOLD_VAL);
    fmrx_set_rf_cap(FMRX_RFCAP_VAL);         //FMFE input capacitor
#if FMRX_REC_EN
    rec_src.spr = SPR_44100;
    if (DAC_OUT_SPR == DAC_OUT_48K) {
        rec_src.spr = SPR_48000;
    }
#if KARAOK_REC_EN
    rec_src.nchannel = 0x11;
#else
    rec_src.nchannel = 0x02;
#endif
    rec_src.source_start = fmrx_rec_start;
    rec_src.source_stop  = fmrx_rec_stop;
#endif
}

AT(.text.bsp.fmrx)
void bsp_fmrx_exit(void)
{
    fmrx_power_off();
}


AT(.text.bsp.fmrx)
void bsp_fmrx_set_freq(u16 freq)
{
    fmrx_set_freq(freq);
#if FMRX_CS_FILTER_WIDER
    //库中默认是cs_filter是25K(实测约54K的调制深度不失真),指标测试时调制深度继续加若看到失真,可以把该宏打开,让cs_filter继续加大
    //但cs_filter带宽越大，放进来的底噪就越多。实际使用时,cs_filter配置成25K够了
    fmrx_sel_cs_filter(CS_FILTER_75K);
#endif
}


AT(.text.bsp.fmrx)
u8 bsp_fmrx_check_freq(u16 freq)
{
    return fmrx_check_freq(freq);
}

AT(.text.bsp.fmrx)
void bsp_fmrx_logger_out(void)
{
    printf("Seek out radio stations(%d):\n", fmrx_cb.ch_cnt);
    for (u8 j = 1; j <= fmrx_cb.ch_cnt; j++) {
        printf("%d\n", get_ch_freq(j));
    }
    fmrx_logger_out();
}


#if FMRX_TEST_TBL_FREQ
static const u16 fm_test_freq_tbl[] = {8750,8780, 8880,8980, 9050,9070, 9150,9180,9200,9280,9390,9510,9640,9670,9710,9800,9910,9950,10000,10070,10160,10300,10380,10400,10430,10490,10540,10710};
static u8 fm_test_ch = 0;
u16 get_fmrx_test_freq_first_ch(void)
{
    fm_test_ch = 0;
    return fm_test_freq_tbl[0];
}

void fmrx_test_freq_sw(u8 dir)
{
    int total_ch = sizeof(fm_test_freq_tbl)/2;
    if (dir) {
        fm_test_ch++;
        if (fm_test_ch >= total_ch) {
            fm_test_ch = 0;
        }
    } else {
        if (fm_test_ch > 0) {
            fm_test_ch--;
        } else {
            fm_test_ch = total_ch-1;
        }
    }
    fmrx_cb.freq = fm_test_freq_tbl[fm_test_ch];
    printf("fm_test_ch = %d, freq = %d\n",fm_test_ch,fmrx_cb.freq);
    bsp_fmrx_set_freq(fmrx_cb.freq);
}
#endif



#if FMRX_OPTIMIZE_TRY
static u32 gat0_bak,gat1_bak,clkcon2_bak,clkcon3_bak;
static const char gat0dis_tbl[] = {9,6,7,11,18,25,28,29,30,31}; //20,26,14,24
static const char gat1dis_tbl[] = {26,0,1,3,4,5,6,7,8,9,10,11,12,13,14,26,27,28,30,31}; //3 是红外时钟，如果要使用红外，需要去掉3

AT(.text.func.fmrx)
void chip_clk_gat_set(void)
{
    int i = 0;
    u32 gat0num = sizeof(gat0dis_tbl);
    u32 gat1num = sizeof(gat1dis_tbl);

    u32 gat0 = 0;
    for(i = 0; i < gat0num; i++) {
        gat0 |= BIT((u32)gat0dis_tbl[i]);
    }
    CLKGAT0 &= ~gat0;
    printf("gat0num = %d,0x%X\n",gat0num,~gat0);
    u32 gat1 = 0;
    for(i = 0; i < gat1num; i++) {
        gat1 |= BIT((u32)gat1dis_tbl[i]);
    }
    CLKGAT1 &= ~gat1;
    printf("gat1num = %d,0x%X\n",gat1num,~gat1);
}

#define CLK_DIV_TEST   0x01     //(1~15)
AT(.text.func.fmrx)
void chip_clk_div_set(void)
{
    CLKCON2 =  (CLKCON2 & (~(0xF<<13))) | (CLK_DIV_TEST << 13);
    CLKCON3 =  (CLKCON3 & (~(0xF<<12))) | (CLK_DIV_TEST << 12);
    CLKCON3 =  (CLKCON3 & (~(0xF<<0))) | (CLK_DIV_TEST << 0);
    CLKCON3 =  (CLKCON3 & (~(0xF<<4))) | (CLK_DIV_TEST << 4);
    CLKCON3 =  (CLKCON3 & (~(0xF<<19))) | (CLK_DIV_TEST <<19);
    CLKCON3 =  (CLKCON3 & (~(0xF<<27))) | (CLK_DIV_TEST <<27);
    CLKCON3 =  (CLKCON3 & (~(0xF<<23))) | (CLK_DIV_TEST <<23);
}

AT(.text.func.fmrx)
void fmop_clk_gat_set(void)
{
    gat0_bak = CLKGAT0;
    gat1_bak = CLKGAT1;
    clkcon2_bak = CLKCON2;
    clkcon3_bak = CLKCON3;
    chip_clk_div_set();
    chip_clk_gat_set();
}

AT(.text.func.fmrx)
void fmop_clk_gat_recover(void)
{
    CLKGAT0 = gat0_bak;
    CLKGAT1 = gat1_bak;
    CLKCON2 = clkcon2_bak;
    CLKCON3 = clkcon3_bak;
}

AT(.text.fmrx)
u8 fmrx_dc_more_ch(void)   //打开这个函数，返回位为1越多，判台时放进来的台越多
{
    return BIT(0);
}
#endif

#endif // FUNC_FMRX_EN

